package me.stone.stanimeclient.core.ui.binding.item

import android.view.View
import android.widget.CompoundButton
import android.widget.CompoundButton.OnCheckedChangeListener
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import timber.log.Timber

open class PlayerBottomMenuItem private constructor(
    val icon: Int, val name: String,
    private val coroutineScope: CoroutineScope
): OnTabSelectedListener, OnCheckedChangeListener, View.OnClickListener {

    companion object {
        fun createTabsMenu(
            icon: Int, name: String, coroutineScope: CoroutineScope,
            tabs: List<CharSequence>, currentTabPos: Int
        ) = PlayerBottomMenuItem(icon, name, coroutineScope).apply {
            menuType = MenuType.Tabs
            dataTabs = tabs
            dataTabsPos = currentTabPos
        }

        fun createSwitchMenu(
            icon: Int, name: String, coroutineScope: CoroutineScope,
            initializeChecked: Boolean
        ) = PlayerBottomMenuItem(icon, name, coroutineScope).apply {
            menuType = MenuType.Switch
            dataChecked = initializeChecked
        }

        fun createDescriptionMenu(
            icon: Int, name: String, coroutineScope: CoroutineScope,
            description: String
        ) = PlayerBottomMenuItem(icon, name, coroutineScope).apply {
            menuType = MenuType.Description
            dataDescription = description
        }

        fun createEnterMenu(
            icon: Int, name: String, coroutineScope: CoroutineScope
        ) = PlayerBottomMenuItem(icon, name, coroutineScope).apply {
            menuType = MenuType.Enter
        }
    }


    private enum class MenuType {
        Tabs, Switch, Description, Enter
    }

    private lateinit var menuType: MenuType

    private var dataChecked: Boolean? = null
        set(value) {
            if (field == value) return
            field = value
            coroutineScope.launch { mChecked.emit(value ?: false) }
        }

    private var dataTabsPos: Int? = null
        set(value) {
            if (field == value) return
            field = value
            coroutineScope.launch { mSelectedTabPos.emit(value ?: 0) }
        }

    private var dataTabs: List<CharSequence>? = null
        set(value) {
            field = value
            coroutineScope.launch { mTabTitles.emit(value ?: emptyList()) }
        }

    private var dataDescription: String? = null
        set(value) {
            if (field == value) return
            field = value
            coroutineScope.launch { mDescription.emit(value ?: "") }
        }


    private val mTabTitles = MutableStateFlow(dataTabs ?: emptyList())
    val tabTitles: StateFlow<List<CharSequence>> = mTabTitles

    private val mSelectedTabPos = MutableStateFlow(dataTabsPos ?: 0)
    val selectedTabPos: StateFlow<Int> = mSelectedTabPos

    private val mChecked = MutableStateFlow(dataChecked ?: false)
    val checked: StateFlow<Boolean> = mChecked

    private val mDescription = MutableStateFlow(dataDescription ?: "")
    val description: StateFlow<String> = mDescription


    fun updateTabs(tabs: List<CharSequence>) = coroutineScope.launch {
        dataTabs = tabs
        mTabTitles.emit(tabs)
    }

    fun updateSelectedTapPos(pos: Int) = coroutineScope.launch {
        if (pos == dataTabsPos) return@launch
        mSelectedTabPos.emit(pos)
    }

    fun updateChecked(checked: Boolean) = coroutineScope.launch {
        if (checked == dataChecked) return@launch
        mChecked.emit(checked)
    }

    fun updateDescription(description: String) = coroutineScope.launch {
        if (description == dataDescription) return@launch
        mDescription.emit(description)
    }


    val showTabs: Boolean
        get() = menuType == MenuType.Tabs

    val showSwitch: Boolean
        get() = menuType == MenuType.Switch

    val showDescription: Boolean
        get() = menuType == MenuType.Description

    val showEnterIcon: Boolean
        get() = menuType == MenuType.Enter

    var showDivider: Boolean = true


    private val mSelectedTab = MutableSharedFlow<Int>()
    val selectedTabChanged: SharedFlow<Int> = mSelectedTab

    private val mCheckedChanged = MutableSharedFlow<Boolean>()
    val checkedChange: SharedFlow<Boolean> = mCheckedChanged

    private val mClickSign = MutableSharedFlow<Unit>()
    val clickSign = mClickSign


    override fun onClick(v: View) {
        when (menuType) {
            MenuType.Tabs -> {}
            MenuType.Switch -> { dataChecked = !(dataChecked ?: false) }
            else -> coroutineScope.launch { mClickSign.emit(Unit) }
        }
    }

    override fun onTabSelected(tab: TabLayout.Tab) {
        if (menuType != MenuType.Tabs) return
        if (dataTabsPos == tab.position) return
        dataTabsPos = tab.position
        coroutineScope.launch { mSelectedTab.emit(tab.position) }
    }

    override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
        if (menuType != MenuType.Switch) return
        if (isChecked == dataChecked) return
        dataChecked = isChecked
        coroutineScope.launch { mCheckedChanged.emit(isChecked) }
    }


    override fun onTabUnselected(tab: TabLayout.Tab?) { }

    override fun onTabReselected(tab: TabLayout.Tab?) { }

}